# -*- coding: utf-8 -*-

# Copyright (c) Huoty, All rights reserved
# Author: Huoty <sudohuoty@163.com>
# CreateTime: 2021-02-25 13:08:25

import os  # noqa
import sys
import socket
import random  # noqa
import logging
import datetime
import warnings
import traceback
import functools
from pprint import pprint as pp
from datetime import (  # noqa
    datetime as DateTime,
    date as Date,
    timedelta as TimeDelta,
)


get_today = datetime.date.today
get_now = datetime.datetime.now


def _import_module(name):
    try:
        return __import__(name)
    except ImportError:
        return None


class _suppress(object):

    def __init__(self, *exceptions):
        self.exceptions = exceptions

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type is not None and issubclass(exc_type, self.exceptions):
            return True


pd = pandas = _import_module("pandas")
np = numpy = _import_module("numpy")


if np:
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=DeprecationWarning)
        if not hasattr(np, 'int'):
            np.int = np.int64
        if not hasattr(np, 'float'):
            np.float = np.float64


if pandas:
    pd.set_option('display.precision', 12)
    pd.set_option('display.max_columns', 50)
    pd.set_option('display.max_rows', 200)
    pd.set_option('display.max_colwidth', 100)


def create_random_dataframe(shape=None, index=None, columns=None):
    if shape is None:
        assert index is not None and columns is not None
        shape = len(index), len(columns)
    data = np.random.rand(*shape)
    return pd.DataFrame(data, index=index, columns=columns)


def telnet(host, port=80, timeout=5):
    try:
        # 创建一个 socket 对象
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            # 设置超时时间
            sock.settimeout(timeout)
            # 连接到指定的主机和端口
            sock.connect((host, port))
            print("Connected to (%s %s)" % (host, port))

            # 等待接收来自服务器的数据
            try:
                welcome_message = sock.recv(1024).decode('utf-8')
                if welcome_message:
                    print("Received message: %s" % welcome_message)
            except socket.timeout:
                print("Timed out waiting for welcome message.")
    except socket.error as ex:
        print("Error connecting to (%s %s) - %s" % (host, port, ex))


def print_exception(ex, file=sys.stderr):
    """打印异常栈"""
    traceback.print_exception(type(ex), ex, ex.__traceback__, file=file)


def setup_exception_hook():
    # 打印异常时打印时间

    def exception_hook(type, value, tb):
        error_stack = ''.join(traceback.format_exception(type, value, tb))
        logging.error("program exception: %s\n%s", value, error_stack)

    sys.excepthook = exception_hook


def setup_logging(reset=False, level="INFO", format=None, file=sys.stdout,
                  error_file=None):
    """初始化日志模块"""
    logger = logging.getLogger()
    if len(logger.handlers) > 0 and not reset:
        logger.debug("logger has been set up")
        return

    for handler in logger.handlers[:]:
        logger.removeHandler(handler)
        handler.close()

    level = level.upper()
    logger.setLevel(level)

    if not format:
        format = ('[%(asctime)s] [%(name)s] [%(process)d] [%(levelname)s] '
                  '%(message)s')
    formatter = logging.Formatter(format)

    FileHandler = functools.partial(
        logging.FileHandler,
        mode='a', encoding='utf8', delay=False,
    )

    if hasattr(file, "write"):
        handler = logging.StreamHandler(file)
    else:
        handler = FileHandler(file)
    handler.setFormatter(formatter)
    handler.setLevel(level)
    logger.addHandler(handler)

    if error_file is not None:
        if hasattr(error_file, "write"):
            error_handler = logging.StreamHandler(error_file)
        else:
            error_handler = FileHandler(error_file)
        error_handler.setFormatter(formatter)
        error_handler.setLevel('ERROR')
        logger.addHandler(error_handler)

    setup_exception_hook()


# load autoimport extension: https://github.com/anntzer/ipython-autoimport
with _suppress(Exception):
    get_ipython().run_line_magic('load_ext', 'ipython_autoimport')  # noqa

# load line_profiler extension,: depend package line_profiler
with _suppress(Exception):
    get_ipython().run_line_magic('load_ext', 'line_profiler')

# load Cython extension, depend packages: cython, ipython-cython
with _suppress(Exception):
    get_ipython().run_line_magic('load_ext', 'Cython')

# load kictor extension: https://github.com/kuanghy/kictor
with _suppress(Exception):
    get_ipython().run_line_magic('load_ext', 'kictor')

# load language magic extension
with _suppress(Exception):
    get_ipython().run_line_magic('load_ext', 'ipython_language_magic')
